package util;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class BeanMapUtil {

	private static final Log logger = LogFactory.getLog(BeanMapUtil.class);

	private static final String SET_METHOD_PREFIX = "set";
	
	private static final Set<String> EXCLUDE_METHOD = new HashSet<String>();

	static {
		EXCLUDE_METHOD.add("getClass");
	}
	/**
	 * 
	 * @param object
	 * @return
	 */
	public static Map<String, Object> object2Map(Object object) {
		Map<String, Object> map_obj = new HashMap<String, Object>();
		if (object == null) {
			return map_obj;
		}
		if (object instanceof String) {
			map_obj.put("stringValue", object);
			return map_obj;
		}

		Class<?> clazz = object.getClass();
		if (clazz == null) {
			return map_obj;
		}
		Method[] methods = clazz.getMethods();

		List<Method> getterMethods = new ArrayList<Method>();
		List<String> getterFields = new ArrayList<String>();

		for (Method method : methods) {
			if (method == null) {
				continue;
			}

			String name = method.getName();
			if(EXCLUDE_METHOD.contains(name)) continue;
			
			Class<?>[] types = method.getParameterTypes();
			Class<?> returnType = method.getReturnType();

			if (types.length == 0
					&& ((name.startsWith("get") && !returnType.equals(void.class)) || (name.startsWith("is") && (returnType
							.equals(java.lang.Boolean.class) || returnType
							.equals(boolean.class))))) {
				if (name.startsWith("get")) {
					name = name.substring(3);
				} else if (name.startsWith("is")) {
					name = name.substring(2);
				}
				if (StringUtils.isNotBlank(name)) {
					name = name.substring(0, 1).toLowerCase()
							+ name.substring(1, name.length());// ��һ����ĸСд

					getterMethods.add(method);
					String fieldName = StringUtils.substring(name, 0, 1)
							.toLowerCase()
							+ StringUtils.substring(name, 1, name.length());
					getterFields.add(fieldName);
				}
			}
		}

		Iterator<Method> methodIterator = getterMethods.iterator();
		Iterator<String> fieldIterator = getterFields.iterator();

		while (methodIterator.hasNext() && fieldIterator.hasNext()) {
			Method method = methodIterator.next();
			String field = fieldIterator.next();
			try {
				Object value = method.invoke(object, new Object[0]);
				map_obj.put(field, value);
			} catch (Throwable t) {
				logger.error("get " + field + " error", t);
			}
		}

		return map_obj;
	}

	public static Object map2Object(Map<String, Object> map, Class<?> classOfT) {
		Object obj = null;
		try {
			obj = classOfT.newInstance();
			Method[] methods = classOfT.getMethods();
			Map<String, Class<?>[]> methodMeta = new HashMap<String, Class<?>[]>();
			for (Method method : methods) {
				methodMeta.put(method.getName(), method.getParameterTypes());
			}
			Set<String> fieldSet = map.keySet();
			Method fieldSetMethod = null;
			for (String field : fieldSet) {
				Object value = map.get(field);
				String methodName = SET_METHOD_PREFIX
						+ field.substring(0, 1).toUpperCase()
						+ field.substring(1, field.length());
				try {
					fieldSetMethod = classOfT.getMethod(methodName, methodMeta
						.get(methodName));
					fieldSetMethod.invoke(obj, value);
				}catch(Throwable t) {
					logger.error(field + " no set Method", t);
				}
			}
		} catch (Throwable t) {
			t.printStackTrace();
		}
		return obj;
	}

}
